package com.geekbang.rpcfx.client;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.geekbang.rpcfx.api.RpcfxRequest;
import com.geekbang.rpcfx.api.RpcfxResponse;
import com.geekbang.rpcfx.client.call.RpcCall;
import com.geekbang.rpcfx.exception.CallException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Objects;

public final class Rpcfx {

    static {
        ParserConfig.getGlobalInstance().addAccept("com.geekbang");
    }

    public static <T> T create(final Class<T> serviceClass, final String url ,RpcCall rpcCall) {
        // 0. 替换动态代理 -> AOP
       return  (T) Enhancer.create(serviceClass, new RpcfxInterceptor(serviceClass, url, rpcCall));

    }

    public static  class RpcfxInterceptor<T> implements MethodInterceptor {
        private final Class<T> serviceClass;
        private final String url;
        private final RpcCall rpcCall;

        public static final MediaType JSONTYPE = MediaType.get("application/json; charset=utf-8");

        public RpcfxInterceptor(Class<T> serviceClass, String url, RpcCall rpcCall) {
            this.serviceClass = serviceClass;
            this.url = url;
            this.rpcCall = rpcCall;
        }
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            RpcfxRequest<T> request = new RpcfxRequest();
            request.setServiceClass(this.serviceClass);
            request.setMethod(method.getName());
            request.setParams(objects);
            RpcfxResponse response = rpcCall.post(request, url);
            return JSON.parse(handleException(response).toString());
        }

        private Object handleException(RpcfxResponse response) {
            if (response.getStatus()) {
                return response.getResult();
            }

            CallException callException = response.getException();
            if (callException != null) {
                throw callException;
            }
            throw new CallException(-1,"system error");
        }
    }
}
